#include "zookeeperutil.h"
#include "myrpcapplication.h"
#include "myrpclogger.h"
#include <mutex>
#include <condition_variable>
#include <iostream>

std::mutex cv_mutex; // 使用全局锁
std::condition_variable cv; // 使用全局信号量
bool is_connected = false;

void global_watcher(zhandle_t *zh, int type, int status, const char* path, void* watcherCtx) {
    if (type == ZOO_SESSION_EVENT) {
        // 当前是会话事件
        if (status == ZOO_CONNECTED_STATE) {
            // 如果是连接状态
            // 加锁
            std::lock_guard<std::mutex> lock(cv_mutex);
            is_connected = true;
        }
    }
    cv.notify_all();
}
ZKClient::ZKClient()
:m_zhandle(nullptr)
{}

ZKClient::~ZKClient()
{
    if (m_zhandle != nullptr) {
        zookeeper_close(m_zhandle);
    }
}

void ZKClient::Start() {
    // 获取zookeeper的ip和port
    std::string ip = MyRPCApplication::getInstance().getConfig().load("zookeeperip");
    std::string port = MyRPCApplication::getInstance().getConfig().load("zookeeperport");
    std::string connstr = ip + ":" + port;

    std::cout << "connstr: " << connstr << "\n";
    // 1、首先初始化一个zookeeper对象
    // 异步建立rpcserver和zookeeper的连接
    m_zhandle = zookeeper_init(connstr.c_str(), global_watcher, 3000, nullptr, nullptr, 0);
    if (m_zhandle == nullptr) {
        LOG(ERROR) << "zookeeper_init error";
        exit(EXIT_FAILURE);
    }

    std::unique_lock<std::mutex> lock(cv_mutex);
    // 2、发起连接后进行等待，等待连接建立完成
    cv.wait(lock,[]{return is_connected;});
    LOG(INFO) << "zookeeper_init success";
}

void ZKClient::Create(const char* path, const char* data, int datalen, int state) {
    // 创建znode结点
    char path_buffer[128];
    int bufferlen = sizeof(path_buffer);
    int flag = zoo_exists(m_zhandle,path,0,nullptr);
    if (flag == ZNONODE) {
        // 说明结点不存在
        // 那就进行创建
        flag = zoo_create(m_zhandle,path,data,datalen,&ZOO_OPEN_ACL_UNSAFE,state,path_buffer,bufferlen);
        if (flag == ZOK) {
            LOG(INFO) << "znode create success... path:" << path;
        } else {
            LOG(ERROR) << "znode create failed... ";
            exit(EXIT_FAILURE);
        }
    }
}

std::string ZKClient::GetData(const char* path) {
    char buf[64];
    int bufflen = sizeof(buf);
    int flag = zoo_get(m_zhandle,path,0,buf,&bufflen,nullptr);
    if (flag != ZOK) {
        LOG(ERROR) << "zoo_get error";
        return "";
    } else {
        return buf;
    }
    return "";
}

